package com.hfdg.prototype.base.generator;


import com.alibaba.druid.pool.DruidDataSource;
import com.hfdg.content.entity.Content;
import com.hfdg.prototype.base.annotations.Table;
import com.hfdg.prototype.base.model.FieldModel;
import com.hfdg.prototype.base.utils.CamelUtils;
import com.hfdg.prototype.base.utils.SqlBuilder;
import com.hfdg.prototype.base.utils.TimeUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName CodeGenerator
 * @Description TODO 代码生成器
 * @Author yuelh
 * @Date 2019/1/17 19:15
 * @Version 1.0
 * @Company 会飞的锅工作室
 **/
@Deprecated
public class CodeGeneratorFromDB {
    private static final String AUTHOR = "yuelh";
    private static final String BASE_PATH = "D:/gen/";
    private static final Resource RESOURCE = new ClassPathResource("gen");
    private static String category;
    private static Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
    private static File baseDir;
    static JdbcTemplate jdbcTemplate;
    static String basePackage;

    static {
        baseDir = new File(BASE_PATH);
        if (!baseDir.exists()) {
            baseDir.mkdirs();
        }
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/prototype?useSSL=false&serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&autoReconnect=true&failOverReadOnly=false&useUnicode=true&characterEncoding=UTF-8\n");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("123456");
        jdbcTemplate = new JdbcTemplate(druidDataSource);

    }

    /*
     * @Author yuelh
     * @Company hfdg
     * @Description //TODO   mapper生成，含xml以及接口类
     * @Date 19:22 2019/1/17
     * @Param [clazz]
     * @return void
     **/
    public static void generateMapperXml(Class<?> clazz) {
        try {
            configuration.setDirectoryForTemplateLoading(RESOURCE.getFile());
            File xmlMapperFile = RESOURCE.getFile();
            Template mapperXml = configuration.getTemplate("mapperXml.ftl");
            Field[] fields = FieldUtils.getAllFields(clazz);
            List<String> columnList = new ArrayList<>();
            List<ColumnField> columnFieldList = new ArrayList<>();
            for (Field field : fields) {
                columnList.add(CamelUtils.camel2Underline(field.getName()));
                columnFieldList.add(ColumnField.build(field));
            }
            String tableName = clazz.getAnnotation(Table.class).name();
            Map<String, Object> params = new HashMap<>();
            params.put("fields", fields);
            params.put("columnList", columnList);
            params.put("columnFieldList", columnFieldList);
            params.put("tableName", tableName);
            params.put("tableInitSql", SqlBuilder.tableInit(clazz));
            params.put("type", clazz.getName());
            String packageName = ClassUtils.getPackageName(clazz);
            params.put("namespace", packageName.substring(0, packageName.lastIndexOf(".")) + ".mapper." + clazz.getSimpleName() + "Mapper");
            String mapperPackage = packageName.substring(0, packageName.lastIndexOf(".")) + ".mapper";
            String mapperRelativePath = mapperPackage.replace(".", "\\");
            File mapperXmlBaseDir = new File(baseDir + File.separator + "resources" + File.separator + mapperRelativePath + File.separator);
            if (!mapperXmlBaseDir.exists()) {
                mapperXmlBaseDir.mkdirs();
            }
            File mapperXmlFile = new File(mapperXmlBaseDir, clazz.getSimpleName() + "Mapper.xml");
            if (!mapperXmlFile.exists()) {
                mapperXmlFile.createNewFile();
            }
//            File xmlFile = new File(baseDir,clazz.getSimpleName()+"Mapper.xml");
//            if(!xmlFile.exists()){
//                xmlFile.createNewFile();
//            }
            mapperXml.process(params, new FileWriter(mapperXmlFile));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        }
    }

    /*
     * @Author yuelh
     * @Company hfdg
     * @Description //TODO  生成Mapper 接口类
     * @Date 11:38 2019/1/19
     * @Param [clazz]  要操作的数据库表对应的实体类
     * @return void
     **/
    public static void generateMapper(Class<?> clazz) {
        try {
            configuration.setDirectoryForTemplateLoading(RESOURCE.getFile());
            File xmlMapperFile = RESOURCE.getFile();
            Template mapper = configuration.getTemplate("mapper.ftl");
            String modelPackage = ClassUtils.getPackageName(clazz);
            String mapperPackage = modelPackage.substring(0, modelPackage.lastIndexOf(".")) + ".mapper";
            String modelFullName = clazz.getName();
            String modelSimpleName = clazz.getSimpleName();
            Map<String, Object> root = new HashMap<>();
            root.put("mapperPackage", mapperPackage);
            root.put("modelName", clazz.getSimpleName());
            root.put("mapperName", clazz.getSimpleName() + "Mapper");
            root.put("modelFullName", modelFullName);
            root.put("author", AUTHOR);
            root.put("createTime", TimeUtils.getTime("yyyy-MM-dd HH:mm:ss"));
            String mapperRelativePath = mapperPackage.replace(".", "\\");
            File mapperBaseDir = new File(baseDir + File.separator + mapperRelativePath + File.separator);
            if (!mapperBaseDir.exists()) {
                mapperBaseDir.mkdirs();
            }
            File mapperFile = new File(mapperBaseDir, clazz.getSimpleName() + "Mapper.java");
            if (!mapperFile.exists()) {
                mapperFile.createNewFile();
            }
            mapper.process(root, new FileWriter(mapperFile));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        }
    }

    public static void generateService(Class<?> clazz) {
        try {
            configuration.setDirectoryForTemplateLoading(RESOURCE.getFile());
            File xmlMapperFile = RESOURCE.getFile();
            Template service = configuration.getTemplate("service.ftl");
            Template serviceImpl = configuration.getTemplate("serviceImpl.ftl");
            String modelName = clazz.getSimpleName();
            String modelFullName = clazz.getName();
            String modelPackage = ClassUtils.getPackageName(clazz);
            String mapperPackage = modelPackage.substring(0, modelPackage.lastIndexOf(".")) + ".mapper";
            String servicePackage = modelPackage.substring(0, modelPackage.lastIndexOf(".")) + ".service";
            String serviceImplPackage = modelPackage.substring(0, modelPackage.lastIndexOf(".")) + ".serviceImpl";
            String modelSimpleName = clazz.getSimpleName();
            Map<String, Object> root = new HashMap<>();
            root.put("modelName", modelName);
            root.put("modelPackage", modelPackage);
            root.put("mapperPackage", mapperPackage);
            root.put("servicePackage", servicePackage);
            root.put("author", AUTHOR);
            String serviceRelativePath = servicePackage.replace(".", "\\");
            File serviceBaseDir = new File(baseDir + File.separator + serviceRelativePath + File.separator);
            if (!serviceBaseDir.exists()) {
                serviceBaseDir.mkdirs();
            }
            File serviceImplBaseDir = new File(baseDir + File.separator + serviceRelativePath + File.separator + "impl" + File.separator);
            if (!serviceImplBaseDir.exists()) {
                serviceImplBaseDir.mkdirs();
            }
            File serviceFile = new File(serviceBaseDir, modelName + "Service.java");
            File serviceImplFile = new File(serviceImplBaseDir, modelName + "ServiceImpl.java");
            if (!serviceFile.exists()) {
                serviceFile.createNewFile();
            }
            if (!serviceImplFile.exists()) {
                serviceImplFile.createNewFile();
            }
            service.process(root, new FileWriter(serviceFile));
            serviceImpl.process(root, new FileWriter(serviceImplFile));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        }
    }

    public static void generateCtrl(Class<?> clazz) {
        try {
            configuration.setDirectoryForTemplateLoading(RESOURCE.getFile());
            File xmlMapperFile = RESOURCE.getFile();
            Template ctrl = configuration.getTemplate("ctrl.ftl");
            String modelName = clazz.getSimpleName();
            String modelFullName = clazz.getName();
            String modelPackage = ClassUtils.getPackageName(clazz);
            String ctrlPackage = modelPackage.substring(0, modelPackage.lastIndexOf(".")) + ".ctrl";
            String servicePackage = modelPackage.substring(0, modelPackage.lastIndexOf(".")) + ".service";
            Map<String, Object> root = new HashMap<>();
            root.put("modelName", modelName);
            root.put("modelPackage", modelPackage);
            root.put("ctrlPackage", ctrlPackage);
            root.put("servicePackage", servicePackage);
            root.put("author", AUTHOR);
            root.put("category", category);
            String ctrlRelativePath = ctrlPackage.replace(".", "\\");
            File ctrlBaseDir = new File(baseDir + File.separator + ctrlRelativePath + File.separator);
            if (!ctrlBaseDir.exists()) {
                ctrlBaseDir.mkdirs();
            }
            File ctrlFile = new File(ctrlBaseDir, modelName + "Ctrl.java");
            if (!ctrlFile.exists()) {
                ctrlFile.createNewFile();
            }
            ctrl.process(root, new FileWriter(ctrlFile));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        }
    }

    /**
     * 数据类型转化JAVA
     * @param sqlType：类型名称
     * @return
     */
    public static String sqlTypeToJavaType(String sqlType) {
        if( sqlType == null || sqlType.trim().length() == 0 ) {
            return sqlType;
        }
        sqlType = sqlType.toLowerCase();
        switch(sqlType){
            case "nvarchar":return "String";
            case "char":return "String";
            case "varchar":return "String";
            case "text":return "String";
            case "nchar":return "String";
            case "blob":return "byte[]";
            case "integer":return "Long";
            case "tinyint":return "Integer";
            case "smallint":return "Integer";
            case "int":return "Integer";
            case "mediumint":return "Integer";
            case "bit":return "Boolean";
            case "bigint":return "java.math.BigInteger";
            case "float":return "Fload";
            case "double":return "Double";
            case "decimal":return "java.math.BigDecimal";
            case "boolean":return "Boolean";
            case "id":return "Long";
            case "date":return "java.util.Date";
            case "datetime":return "java.util.Date";
            case "year":return "java.util.Date";
            case "time":return "java.sql.Time";
            case "timestamp":return "java.sql.Timestamp";
            case "numeric":return "java.math.BigDecimal";
            case "real":return "java.math.BigDecimal";
            case "money":return "Double";
            case "smallmoney":return "Double";
            case "image":return "byte[]";
            default:
                System.out.println("-----------------》转化失败：未发现的类型"+sqlType);
                break;
        }
        return sqlType;
    }


    public static void generateEntity(String tableName,String className){
        try {
            String sql = "select column_name,data_type,column_comment,character_maximum_length from information_schema.columns where table_schema='prototype' and table_name='auth_menu'";
            List<FieldModel> fieldModelList = jdbcTemplate.query(sql, new RowMapper<FieldModel>() {
                @Override
                public FieldModel mapRow(ResultSet resultSet, int i) throws SQLException {
                    FieldModel fieldModel = new FieldModel();
                    fieldModel.setFieldName(CamelUtils.underline2Camel(resultSet.getString("column_name")));
                    fieldModel.setFieldComment(resultSet.getString("column_comment"));
                    fieldModel.setLength(resultSet.getInt("character_maximum_length"));
                    fieldModel.setFieldType(sqlTypeToJavaType(resultSet.getString("data_type")));
                    return fieldModel;
                }
            });
            configuration.setDirectoryForTemplateLoading(RESOURCE.getFile());
            File entityrFile = RESOURCE.getFile();
            Template entity = configuration.getTemplate("entity.ftl");

            Map<String,Object> root = new HashMap<>();
            root.put("className",className);
            root.put("basePackage","com.");
            root.put("author",AUTHOR);
            root.put("tableName",tableName);
            root.put("company","天筑科技股份有限公司");
            root.put("fieldModelList",fieldModelList);

            File entityFile = new File(new File("d:/home"),className+".java");
            if(!entityFile.exists()){
                entityFile.createNewFile();
            }
            entity.process(root,new FileWriter(entityFile));

        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {

            generateEntity("auth_menu","Menu");


    }
}
